package com.wkq.net;

import android.content.Context;
import android.util.Log;

//import com.wkq.net.interceptor.MTimeSearchInterceptor;
import com.wkq.net.interceptor.SignEncryptInterceptor;
import com.wkq.net.interceptor.WBCacheInterceptor;
import com.wkq.net.interceptor.WBInterceptor;
import com.wkq.net.logic.callback.DataCallback;

import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import retrofit2.adapter.rxjava2.Result;

import static com.wkq.net.logic.Config.SUCCESS;


/**
 * Created by xiansong on 2017/9/8.
 */

public class ApiRequest<Observable extends io.reactivex.Observable<Result<BaseData>>, BaseData extends BaseInfo> {

    private static final int OKHTTP_KEEP_ALIVE_DURATION_SECONDS = 50;
    private static final String BASE_URL = "https://engcorner.cn/";
    private static final String BASE_LATE_URL = "http://dict-co.iciba.com/";

//    https://engcorner.cn/feed?s={账号id}&syncText=1




    //动态配置BaseUrl
    public static <T> String serviceEndpoint(Class<T> clazz) {
        return BASE_URL;
    }
 public static <T> String serviceTranslate(Class<T> clazz) {
        return BASE_LATE_URL;
    }

    public static <Service, Observable extends io.reactivex.Observable<Result<BaseData>>, BaseData extends BaseInfo>
    ApiRequest<Observable, BaseData> observable(Class<Service> clazz, ApiBuild.Api<Service, Observable, BaseData> api) {
        return observable(clazz, false, api, null);
    }

    public static <Service, Observable extends io.reactivex.Observable<Result<BaseData>>, BaseData extends BaseInfo>
    ApiRequest<Observable, BaseData> observable(Class<Service> clazz, ApiBuild.Api<Service, Observable, BaseData> api, Interceptor interceptor) {
        return observable(clazz, false, api, interceptor);
    }

    public static <Service, Observable extends io.reactivex.Observable<Result<BaseData>>, BaseData extends BaseInfo>
    ApiRequest<Observable, BaseData> observable(Class<Service> clazz, boolean decode, ApiBuild.Api<Service, Observable, BaseData> api, Interceptor interceptor) {
        ApiRequest<Observable, BaseData> request = new ApiRequest<>();
        ApiBuild<Service, Observable, BaseData> build = ApiBuild.service(clazz, api);
        build.setEndpoint(serviceEndpoint(clazz));
        if (interceptor != null) build.addInterceptor(interceptor);
        request.observable = build.build(decode, OKHTTP_KEEP_ALIVE_DURATION_SECONDS);
        return request;
    }




    public static <Service, Observable extends io.reactivex.Observable<Result<BaseData>>, BaseData extends BaseInfo>
    ApiRequest<Observable, BaseData> serviceWB(Class<Service> clazz, ApiBuild.Api<Service, Observable, BaseData> api) {
        return service(clazz, api, new WBInterceptor());
    }


    public static <Service, Observable extends io.reactivex.Observable<Result<BaseData>>, BaseData extends BaseInfo>
    ApiRequest<Observable, BaseData> serviceTranslate(Class<Service> clazz, ApiBuild.Api<Service, Observable, BaseData> api) {
        return serviceTranslate(clazz, api, new WBInterceptor());
    }




    private static <Service> Service service(Class<Service> clazz, Interceptor... interceptor) {
        return service(clazz, false, interceptor);
    }

    private static <Service> Service service(Class<Service> clazz, boolean decode, Interceptor... interceptor) {
        return ApiBuild.service(clazz, null)
                .setEndpoint(serviceEndpoint(clazz))
                .addInterceptor(interceptor)
                .service(decode, OKHTTP_KEEP_ALIVE_DURATION_SECONDS);
    }

    private static <Service, Observable extends io.reactivex.Observable<Result<BaseData>>, BaseData extends BaseInfo>
    ApiRequest<Observable, BaseData> serviceTranslate(Class<Service> clazz, ApiBuild.Api<Service, Observable, BaseData> api, Interceptor... interceptor) {
        return serviceTranslate(clazz, false, api, interceptor);
    }

    private static <Service, Observable extends io.reactivex.Observable<Result<BaseData>>, BaseData extends BaseInfo>
    ApiRequest<Observable, BaseData> service(Class<Service> clazz, ApiBuild.Api<Service, Observable, BaseData> api, Interceptor... interceptor) {
        return service(clazz, false, api, interceptor);
    }

    private static <Service, Observable extends io.reactivex.Observable<Result<BaseData>>, BaseData extends BaseInfo>
    ApiRequest<Observable, BaseData> service(Class<Service> clazz, boolean decode, ApiBuild.Api<Service, Observable, BaseData> api, Interceptor... interceptor) {

        ApiRequest<Observable, BaseData> request = new ApiRequest<>();

        request.observable = ApiBuild.service(clazz, api)
                .setEndpoint(serviceEndpoint(clazz))
                .addInterceptor(interceptor)
                .build(decode, OKHTTP_KEEP_ALIVE_DURATION_SECONDS);

        return request;
    }

    private static <Service, Observable extends io.reactivex.Observable<Result<BaseData>>, BaseData extends BaseInfo>
    ApiRequest<Observable, BaseData> serviceTranslate(Class<Service> clazz, boolean decode, ApiBuild.Api<Service, Observable, BaseData> api, Interceptor... interceptor) {

        ApiRequest<Observable, BaseData> request = new ApiRequest<>();

        request.observable = ApiBuild.service(clazz, api)
                .setEndpoint(serviceTranslate(clazz))
                .addInterceptor(interceptor)
                .build(decode, OKHTTP_KEEP_ALIVE_DURATION_SECONDS);

        return request;
    }


    private static <Service, Observable extends io.reactivex.Observable<Result<BaseData>>, BaseData extends BaseInfo>
    ApiRequest<Observable, BaseData> serviceNewVersion(Class<Service> clazz, boolean decode, ApiBuild.Api<Service, Observable, BaseData> api, long connectTimeout, long readTimeout, Interceptor... interceptor) {

        ApiRequest<Observable, BaseData> request = new ApiRequest<>();

        request.observable = ApiBuild.service(clazz, api)
                .setEndpoint(serviceEndpoint(clazz))
                .setConnectTimeout(connectTimeout)
                .setReadTimeout(readTimeout)
                .addInterceptor(interceptor)
                .build(decode);

        return request;
    }

    private Observable observable;

    private ApiRequest() {
    }

    public static <Observable extends io.reactivex.Observable<Result<BaseData>>, BaseData extends BaseInfo>
    Disposable subscribe(Observable observable, Subscriber<BaseData> subscriber) {
        return observable.take(1)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(subscriber.next, subscriber.error, subscriber.complete, subscriber.subscribe);
    }

    public Disposable subscribe(Subscriber<BaseData> subscriber) {
        return observable.take(1)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(subscriber.next, subscriber.error, subscriber.complete, subscriber.subscribe);
    }

    public Disposable subscribe(Context context, DataCallback<BaseData> callback) {
        Subscriber<BaseData> subscriber = new Subscriber<BaseData>(context) {
            @Override
            public void onCompleted(String s, String s1, BaseData data) {
                if (callback == null) return;
                callback.callback(SUCCESS, "", data);
            }

            @Override
            public void onError(String code, String message) {
                if (callback == null) return;
                int errorCode = -1;
                try {
                    errorCode = Integer.valueOf(code);
                } catch (Exception ignored) {
                }

                Log.e("LynnTest read", code + " \n " + message);
                callback.callback(errorCode, message, null);
            }
        };

        return observable.take(1)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(subscriber.next, subscriber.error, subscriber.complete, subscriber.subscribe);
    }

    public static Disposable loadData(String url, DataCallback<String> callback) {
        return io.reactivex.Observable
                .just(url)
                .map(s -> {
                    Response response = null;
                    String data = null;
                    try {
                        OkHttpClient client = new OkHttpClient();//创建OkHttpClient对象
                        Request request = new Request.Builder().url(url).build();
                        response = client.newCall(request).execute();//得到Response 对
                        if (response.isSuccessful()) data = response.body().string();
                    } catch (Exception e) {
                    }

                    if (data != null) {

                    }
                    return data;
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(s -> callback.callback(0, "", s));
    }
}
